/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.seari.semodbus.main;

import com.seari.semodbus.bean.ModbusDevice;
import com.seari.semodbus.bean.PLCDevice;
import com.seari.semodbus.bean.VirtualModbus;
import com.seari.semodbus.client.PollingTask;
import com.seari.semodbus.server.ModbusSlaveServer;
import com.seari.semodbus.server.RefreshTask;
import com.seari.semodbus.utils.DeviceUtil;
import com.seari.semodbus.utils.MiscTools;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 *
 * @author Rainbow
 */
public class MainController
{
    protected static Logger logger = LoggerFactory.getLogger(MainController.class);
    static List<PLCDevice> devices = new ArrayList<PLCDevice>();
    public static Properties config;
    static String configFilePath = "config.cfg";
    public static VirtualModbus virtualModbus;
    final static int MODBUS_MAX_REG_COUNT = 100;
    static ExecutorService executorService = Executors.newCachedThreadPool();
    public static void main(String[] args) throws InterruptedException
    {
        MainController mc = new MainController();
        mc.init();
        for (PLCDevice device : devices)
        {
            executorService.submit(new PollingTask(device));
        }
        new Thread(new ModbusSlaveServer()).start();
        TimeUnit.SECONDS.sleep(3);
        executorService.submit(new RefreshTask());
    }
    
    public void init()
    {
        try
        {
            //System.out.println(System.getProperty("user.dir"));
            System.setOut(new PrintStream(System.out, true, "UTF-8"));
            config = MiscTools.loadConfig(configFilePath);
        } catch (Exception ex)
        {
            ex.printStackTrace();
        }
        logger.info("init complete");
        String configList = config.getProperty("device_list");
        String[] lists = configList.split("\\|");
        for (int i = 0; i < lists.length; i++) {
            String deviceStr = lists[i];
            String[] strs = deviceStr.split(":");
            if(null != strs && strs[0].equals(DeviceUtil.DEV_MODBUS))
            {
                //处理真实设备配置以供采集
                PLCDevice device = new ModbusDevice();
                device.setIp(config.getProperty(strs[1]+"_ip"));
                device.setPort(Integer.parseInt(config.getProperty(strs[1]+"_port")));
                device.setSlaveID(Integer.parseInt(config.getProperty(strs[1]+"_unit_id")));
                device.setAddress(Integer.parseInt(config.getProperty(strs[1]+"_data_start_position")));
                device.setCount(Integer.parseInt(config.getProperty(strs[1]+"_data_count")));
                device.setVirtualStartPos(Integer.parseInt(config.getProperty(strs[1]+"_virtual_data_start_position")));
                device.setVirtualEndPos(Integer.parseInt(config.getProperty(strs[1]+"_virtual_data_end_position")));
                device.setDeviceSeq(i+1);
                //modbus超长处理
                if(device.getCount() > MODBUS_MAX_REG_COUNT)
                {
                    int count = device.getCount();
                    int tmpStartPos = device.getVirtualStartPos();
                    int tmpAddress = device.getAddress();
                    //超长时拆分成100个寄存器为一个device进行拉取
                    while(count > 0)
                    {
                        PLCDevice tmp = (PLCDevice)device.clone();
                        tmp.setAddress(tmpAddress);
                        if(count - MODBUS_MAX_REG_COUNT > 0)
                        {
                            tmp.setCount(MODBUS_MAX_REG_COUNT); //设置100个寄存器
                            tmp.setVirtualStartPos(tmpStartPos); //计算虚拟modbus设备的起始位置
                            tmp.setVirtualEndPos(tmpStartPos + MODBUS_MAX_REG_COUNT - 1); //计算虚拟modbus设备的结束位置
                            devices.add(tmp);
                            count-=MODBUS_MAX_REG_COUNT;
                        }else{
                            tmp.setCount(count); //拆分至不足100个时，将剩余的设备添加至device
                            tmp.setVirtualStartPos(tmpStartPos);
                            tmp.setVirtualEndPos(tmpStartPos + count - 1);
                            devices.add(tmp);
                            break;
                        }
                        tmpAddress+=MODBUS_MAX_REG_COUNT;
                        tmpStartPos = tmp.getVirtualEndPos() + 1;
                    }
                }else{
                    devices.add(device);
                }
                //处理虚拟MODBUS配置进行映射
                VirtualModbus.devHashMap.put(i+1, device);
                VirtualModbus.posList.add(Integer.parseInt(config.getProperty(strs[1]+"_virtual_data_start_position")));
                VirtualModbus.posList.add(Integer.parseInt(config.getProperty(strs[1]+"_virtual_data_end_position")));
            }
        }
    }
    }
